/*  

Cafechess Library: Cover basic chess programming needs, like GUI, Engine integration, 
FEN and PGN parsing.

                 \\|//
                 (o o)
--------------ooO-(_)-Ooo----------------------------------
Copyright (C) 2009  By Gregory A. Prentice Snoqualmie, WA
                    www.cafechess.org
                    cafechess@comcast.net
                      Oooo
--------------oooO----(  )---------------------------------
              (  )    (_/
               \_)

Microsoft Public License (Ms-PL)
               
Revisions:

Author        Date    Description:

*/
using System;
using System.Text;
using Cafechess.Chess.General;

namespace Cafechess.Chess.Validation
{
  using Bitboard = System.UInt64;

	/// <summary>
	/// This class contains many static member functions that will generate various
	/// bit patterns and tests for piece movement and attacks for you standard chess
	/// pieces and game rules.
	/// </summary>
//[CLSCompliant(false)]
  public class StandardMoves
  {
    public StandardMoves()
    {
    }
    
    /// <summary>
    /// Will count the number of bits that are true.
    /// </summary>
    /// <param name="bits">Bitboard to count</param>
    /// <returns>Number of bits that are true</returns>
    static public int CountBits(Bitboard bits)
    {
      int count = 0;
      Bitboard mask=BitboardSquare.MaskHighBit;
      while(mask != 0)
      {
        if((bits & mask) > 0 )
          count++;
        mask = mask >> 1;
      }
      return count;
    }

    /// <summary>
    /// Translate a bit into a row coordinate.
    /// </summary>
    /// <param name="bit">Single bit set representing piece on board</param>
    /// <returns>row of piece</returns>
    static public int BitRow(Bitboard bit)
    {
      if( (0xFF00000000000000 & bit) != 0 )
        return 8;
      if( (0x00FF000000000000 & bit) != 0 )
        return 7;
      if( (0x0000FF0000000000 & bit) != 0 )
        return 6;
      if( (0x000000FF00000000 & bit) != 0 )
        return 5;
      if( (0x00000000FF000000 & bit) != 0 )
        return 4;
      if( (0x0000000000FF0000 & bit) != 0 )
        return 3;
      if( (0x000000000000FF00 & bit) != 0 )
        return 2;
      if( (0x00000000000000FF & bit) != 0 )
        return 1;
      return 0;
    }

    /// <summary>
    /// Translate a single bit into a column coordinate.
    /// </summary>
    /// <param name="bit">Single bit set representing piece on board</param>
    /// <returns>column of piece</returns>
    static public int BitColm(Bitboard bit)
    {
      if( (0x8080808080808080 & bit) != 0 )
        return 1;
      if( (0x4040404040404040 & bit) != 0 )
        return 2;
      if( (0x2020202020202020 & bit) != 0 )
        return 3;
      if( (0x1010101010101010 & bit) != 0 )
        return 4;
      if( (0x0808080808080808 & bit) != 0 )
        return 5;
      if( (0x0404040404040404 & bit) != 0 )
        return 6;
      if( (0x0202020202020202 & bit) != 0 )
        return 7;
      if( (0x0101010101010101 & bit) != 0 )
        return 8;
      return 0;
    }



    /// <summary>
    /// Returns the Legal moves that a chess piece may make, does not check if a piece
    /// is pinned or a king is castling through check.
    /// </summary>
    /// <param name="piece">Piece to move</param>
    /// <param name="AttackerTable">The Bitboards of the attacking side</param>
    /// <param name="AttackedTable">The Bitboards of the defending side</param>
    /// <returns></returns>
    static public Bitboard LegalMoves(Bitboard mask, Pieces piece, ChessPosition Attacker, ChessPosition Attacked)
    {
      Bitboard legalMoves = 0;
      switch(piece)
      {
        case Pieces.WhiteKing:
        case Pieces.BlackKing:
          legalMoves = KingMoves( Attacker.Color, Attacker.canCastleKingside, Attacker.canCastleQueenside,
            mask, Attacker.Board, Attacked.Board);
          break;
        case Pieces.WhiteQueen:
        case Pieces.BlackQueen:
          legalMoves  = QueenMoves(mask,Attacker.Board,Attacked.Board);
          break;
        case Pieces.WhiteRook:
        case Pieces.BlackRook:
          legalMoves  = RookMoves(mask,Attacker.Board,Attacked.Board);
          break;
        case Pieces.WhiteBishop:
        case Pieces.BlackBishop:
          legalMoves = BishopMoves(mask,Attacker.Board,Attacked.Board);
          break;
        case Pieces.WhiteKnight:
        case Pieces.BlackKnight:
          legalMoves = KnightMoves(mask,Attacker.Board,Attacked.Board);
          break;
        case Pieces.WhitePawn:
        case Pieces.BlackPawn:
          // Get basic pawn moves.
          legalMoves = PawnMoves(mask,Attacker.Color,Attacker.Board,Attacked.Board);
          // Only a legal move if a pawn is attacking a piece.
          legalMoves |= (Attacked.Board & PawnAttacks(mask,Attacker.Color));
          // Get enpassant move          
          legalMoves |= PawnEnpassant(mask, Attacker, Attacked);
          break;
      }
      return legalMoves;
    }

    /// <summary>
    /// Returns the valid moves that a chess piece may make.
    /// </summary>
    /// <param name="piece">the piece moving</param>
    /// <param name="Bitboard"></param>
    /// <returns></returns>
    static public Bitboard PieceMoves(Pieces piece, Bitboard mask)
    {
      Bitboard legalMoves = 0;
      switch(piece)
      {
        case Pieces.WhiteKing:
        case Pieces.BlackKing:
          legalMoves = KingMoves( true, false, false,
            mask, mask, mask);
          break;
        case Pieces.WhiteQueen:
        case Pieces.BlackQueen:
          legalMoves  = QueenMoves(mask,mask,mask);
          break;
        case Pieces.WhiteRook:
        case Pieces.BlackRook:
          legalMoves  = RookMoves(mask,mask,mask);
          break;
        case Pieces.WhiteBishop:
        case Pieces.BlackBishop:
          legalMoves = BishopMoves(mask,mask,mask);
          break;
        case Pieces.WhiteKnight:
        case Pieces.BlackKnight:
          legalMoves = KnightMoves(mask,mask,mask);
          break;
        case Pieces.WhitePawn:
        case Pieces.BlackPawn:
          // Get basic pawn moves.
          legalMoves = PawnMoves(mask,piece==Pieces.WhitePawn?true:false,0,0);
          break;
      }
      return legalMoves;
    }


    /// <summary>
    /// Test to see if the king is in check or the game has ended 
    /// in a Checkmate or Stalemate.
    /// Tests for Stale mate:
    /// <code>
    ///   5k2/5P2/5PK1/8/8/8/8/ b  ok Should be stalemate immediately
    ///   7k/R7/8/8/8/8/8/6R1 b  ok Should be stalemate immediately
    ///   2Q1k3/2p1brpp/8/2q5/8/4R3/PP1N2PP/4R2K b  ok Should be mate immediately
    ///   1k5r/6p1/4qpp1/5p1P/8/P7/KPP5/3q4 w ok Pawn move to black check
    ///   8/5Q2/7k/4R2P/1KP5/p5P1/P7/8 b ok Should be stalemate immediately.
    ///   rnbq1bnr/ppp1pQp1/3kB3/3P4/N4B1p/8/PPP2KPP/R5NR b pawn move two squares not suppressed with piece in the way.
    ///   rnbqkbnr/pppppp1p/6p1/3PP3/3PKP2/3PPP2/7P/RNBQ1BNR b weird enpasant capture to prevent mate
    ///   rnbqkbnr/pppppp1p/6p1/3PB3/3PKP2/3PPP2/7P/RNBQ2NR b weird enpasant can't capture to prevent mate
    ///   rnbqkbnr/1p1ppppp/8/2p1Q3/4N3/4P3/PpPP1PPP/R1B1KBNR w ---- Knight mate with pinned piece.
    /// </code>
    /// </summary>
    /// <param name="Attacker"></param>
    /// <param name="Attacked"></param>
    /// <returns></returns>
    static public bool IsKingCheckedMatedStaled(ChessPosition Attacker, ChessPosition Attacked, AttackingPieces Attacking)
    {
      Bitboard pawnMoves;
      Attacked.IsKingMated = false;
      Attacked.IsKingStaleMated = false;
      // Only test for mate if our opponents king is currently in check.
      if( IsKingInCheck(Attacked, Attacker, Attacking) )
        // Set the flag for use later.
        Attacked.IsKingInCheck = true;
      else
        Attacked.IsKingInCheck = false;

      // Generate the Attacker's moves as if the Attacked king is not there.
      //  This allows us to get rid of any potential king moves that would run past a
      //  king; such as the attack of a rook or bishop.
      // Remove the king
      Attacked.Board = Attacked.Board & ~Attacked.King;
      // Generate all attackes.
      Bitboard attacks = Attacks(Attacker,Attacked, Suppress.GETALL,out pawnMoves);
      // Put king back on board.
      Attacked.Board = Attacked.Board | Attacked.King;
      // Get all of the king moves for the king being attacked and
      //  subtract off the pieces the king protects.  These are the valid moves.
      Bitboard king = (~Attacked.Board & KingMoves(Attacked.Color,false,false,
        Attacked.King,
        Attacked.Board,
        Attacker.Board));
      
      // Lets see if the king can move by complementing the attacks and
      //  anding the result to our king moves.  If we get a value of zero
      //  then the king has no moves available.
      bool KingCantMove =( 0 == (~attacks & king));

      // Is more than one piece attacking the king? If so our only option
      //  was to move the king to safety.
      if( KingCantMove && Attacking.Count > 1 )
      {
        Attacked.IsKingInCheck = true;
        Attacked.IsKingMated = true;
      }
      else if( KingCantMove )
      {        
        // If the king can't move and atleast one attacking piece we need to see if any other piece
        // can attack another attacking piece or 
        // Get all of the leagal moves for the attacked except the king.
        //  We determined above the king could not move out of check or
        //  capture the attacking piece.

        // Generate pinned pieces as we can't use them to interpose.
        Pins(Attacker, Attacked, Attacking);
        // Get our retaliation move but suppress king and some pawn moves.
        //  Note the Attacks() method normally looks for the attacker as the first
        //  parameter and attacked as second, here we switch as we want to see if
        //  we've checkmated the attacked.
        Bitboard retaliate = Attacks(Attacked,Attacker, Suppress.KINGS|Suppress.PAWNILLEGALATTACKS, out pawnMoves);
        Bitboard attackLine=0;
        // The king is in check so now we're checking for check mate.
        if( Attacked.IsKingInCheck )
        {
          if( Attacking.Queen > 0 )
          {
            // First see if we can capture the Queen.
            if( (retaliate & Attacking.Queen) == 0 )
            {
              attackLine = DirectAttack(Attacking.Queen,Attacked.King);
            }
          }
          else if( Attacking.Rook > 0 )
          {
            // First see if we can capture the Rook.
            if( (retaliate & Attacking.Rook) == 0 )
            {
              attackLine = DirectAttack(Attacking.Rook,Attacked.King);
            }

          }
          else if( Attacking.Bishop > 0 )
          {
            // First see if we can capture the Bishop.
            if( (retaliate & Attacking.Bishop) == 0 )
            {
              attackLine = DirectAttack(Attacking.Bishop,Attacked.King);
            }
          }
          else if( Attacking.Knight > 0 )
          {
            // First see if we can capture the Knight.
            if( (retaliate & Attacking.Knight) == 0 )
            {
              // Calculate attacking piece and defending kings common attacks.
              attackLine = Attacking.Knight | Attacked.King;
            }
          }
          else if( Attacking.Pawn > 0 )
          {
            // First see if we can capture the pawn.
            if( (retaliate & Attacking.Pawn) == 0 )
            {
              if((Attacker.Enpassant & Attacking.Pawn) == 0  || Attacked.CaptureEnpassant == 0 )
              {
                // Calculate attacking piece and defending kings common attacks.
                attackLine = DirectAttack(Attacking.Pawn,Attacked.King);
              }
            }
          }          
          // See if we have a direct line of attack as we didn't capture the attacking
          //  piece.
          if( attackLine != 0 )
          { 
            // Suppress pawn attackes from the defender here as they can't interpose
            //  and we've already tested for king moves out of checks above.
            retaliate = Attacks(Attacked,Attacker,Suppress.PAWNATTACKS|Suppress.KINGS, out pawnMoves);
            // Remove the king itself incase it is protected by another piece, add in any pawn moves
            retaliate = pawnMoves | (retaliate & ~Attacked.King);
            // See if a piece can interpose.
            if( (attackLine & ~retaliate) == attackLine )
              Attacked.IsKingMated = true;
            // Clear for now but in future use to optimize move generation.
            Attacked.Pinned = 0x00;
            Attacked.Pinning = 0x00;
          }
        }
        else if( retaliate == 0 && pawnMoves == 0)
        {
          // We're in stalemate.
          Attacked.IsKingStaleMated = true;
        }
      }
      return Attacked.IsKingMated;
    }

    /// <summary>
    /// This routine checks to see if a king is in check by impersonating each
    /// opposite color's pieces and generating legals moves for each piece.
    /// The legal moves are then compared with the kings attackers to determine
    /// whom is attacking the king.  This is an optimization that only requires
    /// us to generate the moves of each of our chess piece types vs the all the
    /// moves of our attackers.
    /// </summary>
    /// <param name="Attacked">Position of side being attacked</param>
    /// <param name="Attacker">Position of side attacking</param>
    /// <param name="Attacking">Used to track all pieces currently attacking the king.</param>
    /// <returns>True if the king is in check.  Also set a </returns>
    static public bool IsKingInCheck(ChessPosition Attacked, ChessPosition Attacker, AttackingPieces Attacking)
    {
      Bitboard mBucket=0;
      Bitboard moves;
      // Used so queen is only counted once by Attacking class.
      Bitboard qmoves;
      Attacking.Clear();
      //-- Used for pin detection. --
      Attacking.DiagonalLR = Attacked.King | DiagonalLR(Attacked.King, 0,0);
      Attacking.DiagonalRL = Attacked.King | DiagonalRL(Attacked.King, 0,0);
      Attacking.Files = Attacked.King | FileMoves(Attacked.King,0,0);
      Attacking.Ranks = Attacked.King | RankMoves(Attacked.King,0,0);
      //---------------------------


      moves = BishopMoves(Attacked.King, Attacked.Board, Attacker.Board);
      Attacking.Bishop = (moves & ~Attacked.Board) & (Bitboard)Attacker.Bishops;
      mBucket |= Attacking.Bishop;

      qmoves = (moves & ~Attacked.Board) & (Bitboard)Attacker.Queens;
      mBucket |= qmoves;

      moves = RookMoves(Attacked.King, Attacked.Board, Attacker.Board);
      Attacking.Rook = (moves & ~Attacked.Board) & Attacker.Rooks;
      mBucket |= Attacking.Rook;
      Attacking.Queen = qmoves | ((moves & ~Attacked.Board) & (Bitboard)Attacker.Queens);
      mBucket |= Attacking.Queen;

      moves = KnightMoves(Attacked.King, Attacked.Board, Attacker.Board);
      Attacking.Knight = (moves & ~Attacked.Board) & Attacker.Knights;
      mBucket |= Attacking.Knight;
      // Only want the attacks of a pawn if there is an opponents piece there.
      moves = (Attacker.Board & PawnAttacks(Attacked.King, Attacked.Color /*, Attacked.Board, Attacker.Board*/));
      Attacking.Pawn = (moves & ~Attacked.Board) & Attacker.Pawns;
      mBucket |= Attacking.Pawn;

      moves = KingMoves(Attacked.Color, Attacked.canCastleKingside, Attacked.canCastleQueenside,
        Attacked.King,Attacked.Board, Attacker.Board);
      mBucket |= (moves & ~Attacked.Board) & (Bitboard)Attacker.King;
      return (mBucket != 0);
    }

    /// <summary>
    /// Generates the bitboards that contain the pinned and pinning pieces.  Used to correctly
    /// generate legal moves for mate/stalemate detection.
    /// </summary>
    /// <param name="Attacker">The position attacking and pinning pieces</param>
    /// <param name="Attacked">The position to find pinned pieces</param>
    /// <param name="Attacking">Used to track all pieces currently attacking the king.</param>
    static public void Pins(ChessPosition Attacker, ChessPosition Attacked, AttackingPieces Attacking)
    {
      //-- Used for pin detection. --
      Attacking.DiagonalLR = DiagonalLR(Attacked.King,0,0);
      Attacking.DiagonalRL = DiagonalRL(Attacked.King,0,0);
      Attacking.Files = FileMoves(Attacked.King,0,0);
      Attacking.Ranks = RankMoves(Attacked.King,0,0);
      Bitboard diagonalLR = DiagonalLR(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard diagonalRL = DiagonalRL(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard files = FileMoves(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard ranks = RankMoves(Attacked.King,Attacked.Board,Attacker.Board);
      //---------------------------
      Bitboard attacked=0;
      Attacked.Pinned = 0;
      Attacked.Pinning = 0;
      Bitboard mask=BitboardSquare.MaskHighBit;
      while(mask != 0)
      {
        attacked = 0;
        if((mask & Attacker.Queens) > 0)
        {
          if((mask & Attacking.Files) > 0)
          {
            attacked = FileMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & files & Attacked.Board;
          }
          else if((mask & Attacking.Ranks) > 0 )
          {
            attacked = RankMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & ranks & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalLR) > 0)
          {
            attacked = DiagonalLR(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalLR & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalRL) > 0)
          {
            attacked = DiagonalRL(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalRL & Attacked.Board;
          }
          if(attacked != 0)
          {
            Attacked.Pinned |= attacked;
            Attacked.Pinning |= mask;
          }

        }
        else if((mask & Attacker.Rooks) > 0)
        {
          if((mask & Attacking.Files) > 0)
          {
            attacked = FileMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & files & Attacked.Board;
          }
          else if((mask & Attacking.Ranks) > 0)
          {
            attacked = RankMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & ranks & Attacked.Board;
          }
          if(attacked != 0)
          {
            Attacked.Pinned |= attacked;
            Attacked.Pinning |= mask;
          }
        }
        else if((mask & Attacker.Bishops) > 0)
        {
          if((mask & Attacking.DiagonalLR) > 0)
          {
            attacked = DiagonalLR(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalLR & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalRL) > 0)
          {
            attacked = DiagonalRL(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalRL & Attacked.Board;
          }
          if(attacked != 0)
          {
            Attacked.Pinned |= attacked;
            Attacked.Pinning |= mask;
          }
        }
        mask = mask >> 1;
      }
    }
    /// <summary>
    /// Used to deterimine what piece is pinning the pinned piece.
    /// This is used mainly in the algebraic move routines to help determine
    /// which piece moved.
    /// </summary>
    /// <param name="pinned">Pinned piece</param>
    /// <param name="Attacker">The position doing the pinning</param>
    /// <param name="Attacked">The position with pinned pieces</param>
    /// <param name="Attacking">Used to track all pieces currently attacking the king.</param>
    /// <returns></returns>
    static public Bitboard PinningPiece(Bitboard pinned, ChessPosition Attacker, ChessPosition Attacked, AttackingPieces Attacking)
    {
      //-- Used for pin detection. --
      Attacking.DiagonalLR = StandardMoves.DiagonalLR(Attacked.King,0,0);
      Attacking.DiagonalRL = StandardMoves.DiagonalRL(Attacked.King,0,0);
      Attacking.Files = StandardMoves.FileMoves(Attacked.King,0,0);
      Attacking.Ranks = StandardMoves.RankMoves(Attacked.King,0,0);
      Bitboard DiagonalLR = StandardMoves.DiagonalLR(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard DiagonalRL = StandardMoves.DiagonalRL(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard Files = StandardMoves.FileMoves(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard Ranks = StandardMoves.RankMoves(Attacked.King,Attacked.Board,Attacker.Board);
      //---------------------------
      Bitboard attacked=0;
      Bitboard Pinning = 0;
      Bitboard mask=BitboardSquare.MaskHighBit;
      while(mask != 0)
      {
        attacked = 0;
        if((mask & Attacker.Queens) > 0)
        {
          if((mask & Attacking.Files) > 0)
          {
            attacked = StandardMoves.FileMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & Files & Attacked.Board;
          }
          else if((mask & Attacking.Ranks) > 0 )
          {
            attacked = StandardMoves.RankMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & Ranks & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalLR) > 0)
          {
            attacked = StandardMoves.DiagonalLR(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & DiagonalLR & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalRL) > 0)
          {
            attacked = StandardMoves.DiagonalRL(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & DiagonalRL & Attacked.Board;
          }
          if((attacked & pinned) !=0)
          {
            Pinning = mask;
            break;
          }

        }
        else if((mask & Attacker.Rooks) > 0)
        {
          if((mask & Attacking.Files) > 0)
          {
            attacked = StandardMoves.FileMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & Files & Attacked.Board;
          }
          else if((mask & Attacking.Ranks) > 0)
          {
            attacked = StandardMoves.RankMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & Ranks & Attacked.Board;
          }
          if((attacked & pinned) !=0)
          {
            Pinning = mask;
            break;
          }
        }
        else if((mask & Attacker.Bishops) > 0)
        {
          if((mask & Attacking.DiagonalLR) > 0)
          {
            attacked = StandardMoves.DiagonalLR(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & DiagonalLR & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalRL) > 0)
          {
            attacked = StandardMoves.DiagonalRL(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & DiagonalRL & Attacked.Board;
          }
          if((attacked & pinned) !=0)
          {
            Pinning = mask;
            break;
          }
        }
        mask = mask >> 1;
      }
      return Pinning;
    }

    /// <summary>
    /// Generates the bitboards that contain the pinned and pinning pieces.  Used to correctly
    /// generate legal moves for mate/stalemate detection.
    /// </summary>
    /// <param name="Attacker">The position attacking and pinning pieces</param>
    /// <param name="Attacked">The position to find pinned pieces</param>
    /// <returns></returns>  
    static public void Pins(Bitboard moveTo, Bitboard canCapture, ChessPosition Attacker, ChessPosition Attacked, AttackingPieces Attacking)
    {
      //-- Used for pin detection. --
      Attacking.DiagonalLR = DiagonalLR(Attacked.King,0,0);
      Attacking.DiagonalRL = DiagonalRL(Attacked.King,0,0);
      Attacking.Files = FileMoves(Attacked.King,0,0);
      Attacking.Ranks = RankMoves(Attacked.King,0,0);
      Bitboard diagonalLR = DiagonalLR(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard diagonalRL = DiagonalRL(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard files = FileMoves(Attacked.King,Attacked.Board,Attacker.Board);
      Bitboard ranks = RankMoves(Attacked.King,Attacked.Board,Attacker.Board);
      //---------------------------
      Bitboard attacked=0;
      Attacked.Pinned = 0;
      Attacked.Pinning = 0;
      Bitboard mask=BitboardSquare.MaskHighBit;
      while(mask != 0)
      {
        attacked = 0;
        if((mask & Attacker.Queens) > 0)
        {
          if((mask & Attacking.Files) > 0)
          {
            attacked = FileMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & files & Attacked.Board;
          }
          else if((mask & Attacking.Ranks) > 0 )
          {
            attacked = RankMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & ranks & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalLR) > 0)
          {
            attacked = DiagonalLR(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalLR & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalRL) > 0)
          {
            attacked = DiagonalRL(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalRL & Attacked.Board;
          }
          if(attacked != 0)
          { 
            if(!((attacked & canCapture) > 0 && mask == moveTo))
            {
              Attacked.Pinned |= attacked;
              Attacked.Pinning |= mask;
            }
          }

        }
        else if((mask & Attacker.Rooks) > 0)
        {
          if((mask & Attacking.Files) > 0)
          {
            attacked = FileMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & files & Attacked.Board;
          }
          else if((mask & Attacking.Ranks) > 0)
          {
            attacked = RankMoves(mask, Attacker.Board, Attacked.Board);
            attacked = attacked & ranks & Attacked.Board;
          }
          if(attacked != 0)
          {
            if(!((attacked & canCapture) > 0 && mask == moveTo))
            {
              Attacked.Pinned |= attacked;
              Attacked.Pinning |= mask;
            }
          }
        }
        else if((mask & Attacker.Bishops) > 0)
        {
          if((mask & Attacking.DiagonalLR) > 0)
          {
            attacked = DiagonalLR(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalLR & Attacked.Board;
          }
          else if((mask & Attacking.DiagonalRL) > 0)
          {
            attacked = DiagonalRL(mask,Attacker.Board,Attacked.Board);
            attacked = attacked & diagonalRL & Attacked.Board;
          }
          if(attacked != 0)
          {
            if(!((attacked & canCapture) > 0 && mask == moveTo))
            {
              Attacked.Pinned |= attacked;
              Attacked.Pinning |= mask;
            }
          }
        }
        mask = mask >> 1;
      }
    }

    /// <summary>
    /// Simply builds a Bitboard with all pieces that are attacking a particular square.
    /// </summary>
    /// <param name="square">Square under attack</param>
    /// <param name="Attacker">Attacker position</param>
    /// <param name="Attacked">Attacked position</param>
    /// <returns></returns>
    static public Bitboard AttackingSquare(Bitboard square, ChessPosition Attacker, ChessPosition Attacked)
    {
      Bitboard attackers=0;
      // Act as if the destination square contains the piece moved to locate
      //  other piece that may move there.
      attackers |= StandardMoves.KingMoves(Attacker.Color,false,false,square,Attacker.Board, Attacked.Board) & Attacker.King;
      // Act as if the destination square contains the piece moved to locate
      //  other piece that may move there.
      attackers |= StandardMoves.QueenMoves(square,Attacker.Board,Attacked.Board) & Attacker.Queens;
      // Act as if the destination square contains the piece moved to locate
      //  other piece that may move there.
      attackers |= StandardMoves.RookMoves(square,Attacker.Board,Attacked.Board) &Attacker.Rooks;
      // Act as if the destination square contains the piece moved to locate
      //  other piece that may move there.
      attackers |= StandardMoves.BishopMoves(square,Attacker.Board,Attacked.Board) & Attacker.Bishops;
      // Act as if the destination square contains the piece moved to locate
      //  other piece that may move there.
      attackers |= StandardMoves.KnightMoves(square,Attacker.Board,Attacked.Board) & Attacker.Knights;
      // Note we need to act like the other colors pawns to determine if we are attacking the square.
      attackers |= StandardMoves.PawnAttacks(square,Attacked.Color) & Attacker.Pawns;
      return attackers;
   }
    /// <summary>
    /// Used to help in piece attack determination, as more than one piece may attack a square
    /// we use this routine when the same type of piece may move to the same square.  Thus we
    /// may have to qualify our moves.
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="square"></param>
    /// <param name="Attacker"></param>
    /// <param name="Attacked"></param>
    /// <returns></returns>
    static public Bitboard AttackingSquare(Pieces piece, Bitboard square, ChessPosition Attacker, ChessPosition Attacked)
    {
      Bitboard mask = 0;
      // Now deterimine if a another piece could have moved to the destination square.
      //  if so we need to qualify which piece moved.
      switch(piece)
      {
        case Pieces.BlackQueen:
        case Pieces.WhiteQueen:
          // Act as if the destination square contains the piece moved to locate
          //  other piece that may move there.
          mask = StandardMoves.QueenMoves(square,Attacker.Board,Attacked.Board) & Attacker.Queens;
          break;
        case Pieces.BlackBishop:
        case Pieces.WhiteBishop:
          // Act as if the destination square contains the piece moved to locate
          //  other piece that may move there.
          mask = StandardMoves.BishopMoves(square,Attacker.Board,Attacked.Board) & Attacker.Bishops;
          break;
        case Pieces.BlackRook:
        case Pieces.WhiteRook:
          // Act as if the destination square contains the piece moved to locate
          //  other piece that may move there.
          mask = StandardMoves.RookMoves(square,Attacker.Board,Attacked.Board) &Attacker.Rooks;
          break;
        case Pieces.BlackKnight:
        case Pieces.WhiteKnight:
          // Act as if the destination square contains the piece moved to locate
          //  other piece that may move there.
          mask = StandardMoves.KnightMoves(square,Attacker.Board,Attacked.Board) & Attacker.Knights;
          break;
        case Pieces.BlackPawn:
        case Pieces.WhitePawn:
        case Pieces.WhiteKing:
        case Pieces.BlackKing:
          mask = 0;
          break;
      }
      return mask;      
    }



    #region chessmoves
    static public Bitboard PawnEnpassant(Bitboard pawn, ChessPosition Attacker, ChessPosition Attacked)
    {
      Bitboard mask = 0;
      // Potential Empasant move available.
      if( Attacked.Enpassant > 0 )
      {
        int rowAttacker = BitRow(pawn);
        int rowAttacked = BitRow(Attacked.Enpassant);
        if( rowAttacker == rowAttacked )
        {
          int colmAttacker = BitColm(pawn);
          int colmAttacked = BitColm(Attacked.Enpassant);
          if( (colmAttacker + 1) == colmAttacked ||
            (colmAttacker - 1) == colmAttacked )
          {
            if( Attacker.Color )
            {
              mask = Attacked.Enpassant << 8;
            }
            else
            {
              mask = Attacked.Enpassant >> 8;
            }
          }
        }
      }
      Attacker.CaptureEnpassant = mask;
      return mask;
    }
    /// <summary>
    /// Returns all of the valid moves for the specified pawn.
    /// Note if you wish to simply get all squares a piece can move
    /// to then simply pass zero for attacker and defender.  If you
    /// do not want to include protected pieces then xor piece board
    /// then AND with function returned value.
    /// </summary>
    /// <param name="bit"></param>
    /// <param name="bit">One bit set for location of biship</param>
    /// <param name="dir">If true then white pawn move</param>
    /// <param name="attacker">The piece board associated with pawn move</param>
    /// <param name="defender">The piece board associated with the opposite color</param>
    /// <returns></returns>
    static public Bitboard PawnMoves(Bitboard bit, bool dir, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket=0,pBit=bit;
      int row=BitRow(bit),colm=BitColm(bit);      
      if( dir )
      {
        bit = bit << 8;
        // Generate first pawn move.
        if( (bit & attacker) == 0 && (bit & defender) == 0 )
          moveBucket |= bit;
        // Generate second pawn move only if first was valid.
        if( moveBucket > 0 && row == 2 )
        {
          bit = bit << 8;
          if( (bit & attacker) == 0 && (bit & defender) == 0 )
            moveBucket |= bit;
        }
      }
      else
      {
        bit = bit >> 8;
        // Generate first pawn move
        if( (bit & attacker) == 0 && (bit & defender) == 0 )
          moveBucket |= bit;
        // Generate second pawn move only if first was valid.
        if( moveBucket > 0 && row == 7 )
        {
          bit = bit >> 8;
          if( (bit & attacker) == 0 && (bit & defender) == 0 )
            moveBucket |= bit;
        }
      }
      return moveBucket;
    }
    /// <summary>
    /// Generates only the square a pawn could attack.
    /// </summary>
    /// <param name="pawn"></param>
    /// <param name="color"></param>
    /// <returns></returns>
    static public Bitboard PawnAttacks(Bitboard pawn, bool color )
    {
      Bitboard moveBucket=0;//,pBit=pawn;
      int row=BitRow(pawn),colm=BitColm(pawn);
      if( color )
      {
        // White pawn
        pawn = pawn << 8;
        if( colm != 8 )
          moveBucket |= (pawn >> 1) ;
        if( colm != 1 )
          moveBucket |= (pawn << 1);
      }
      else
      {
        // Black pawn
        pawn = pawn >> 8;
        if( colm != 8 )
          moveBucket |= (pawn >> 1);
        if( colm != 1 )
          moveBucket |= (pawn << 1);
      }
      return moveBucket;
    }

    /// <summary>
    /// Determines all of the given square a knight may move to, includes it's captures
    /// and piece protection.
    /// </summary>
    /// <param name="bit"></param>
    /// <param name="attacker"></param>
    /// <param name="defender"></param>
    /// <returns></returns>
    static public Bitboard KnightMoves(Bitboard bit, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket,night1=0,night2=0;
      int row=BitRow(bit),colm=BitColm(bit);

      switch(colm)
      {
        case 1:
          night1 = (Bitboard)0xFF &  (Bitboard)(0x05 << 6);
          night2 = (Bitboard)0xFF &  (Bitboard)(0x11 << 5);
          break;
        case 2:
          night1 = 0xFF & (0x05 << 5);
          night2 = 0xFF & (0x11 << 4);
          break;
        case 3:
          night1 = 0xFF & (0x05 << 4);
          night2 = 0xFF & (0x11 << 3);
          break;
        case 4:
          night1 = 0xFF & (0x05 << 3);
          night2 = 0xFF & (0x11 << 2);
          break;
        case 5:
          night1 = 0xFF & (0x05 << 2);
          night2 = 0xFF & (0x11 << 1);
          break;
        case 6:
          night1 = 0xFF & (0x05 << 1);
          night2 = 0x11;
          break;
        case 7:
          night1 = 0x05;
          night2 = 0xFF & (0x11 >> 1);
          break;
        case 8:
          night1 = 0xFF & (0x05 >> 1);
          night2 = 0xFF & (0x11 >> 2);
          break;
      }

      moveBucket = 0;
      if( row < 8 )
        moveBucket |= night2 << (8*row);
      if( row < 7 )
        moveBucket |= night1 << (8*(row+1));
      if( row > 1 )
        moveBucket |= night2 << (8*(row-2));
      if( row > 2 )
        moveBucket |= night1 << (8*(row-3));

      return moveBucket;
    }

    /// <summary>
    /// Determines all of the given square a queen may move to, includes it's captures
    /// and piece protection.
    /// </summary>
    /// <param name="bit"></param>
    /// <param name="attacker"></param>
    /// <param name="defender"></param>
    /// <returns></returns>
    static public Bitboard QueenMoves(Bitboard bit, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket;
      moveBucket  = RankMoves(bit,attacker,defender);
      moveBucket |= FileMoves(bit,attacker,defender);
      moveBucket |= BishopMoves(bit,attacker,defender);
      return moveBucket;
    }
 
    /// <summary>
    /// Determines all of the given squares a rook may move to includes it's captures
    /// and piece protection.
    /// </summary>
    /// <param name="bit"></param>
    /// <param name="attacker"></param>
    /// <param name="defender"></param>
    /// <returns></returns>
    static public Bitboard RookMoves(Bitboard bit, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket;
      moveBucket  = RankMoves(bit,attacker,defender);
      moveBucket |= FileMoves(bit,attacker,defender);
      return moveBucket;
    }

    /// <summary>
    /// Return all valid moves for the king, including pieces it protects.
    /// Note if you wish to simply get all squares a piece can move
    /// to then simply pass zero for attacker and defender.  If you
    /// do not want to include protected pieces then xor piece board
    /// then AND with function returned value.
    /// </summary>
    /// <param name="bColor">If true then it is white to move</param>
    /// <param name="canCastleKingside">If true then caslting kingside is allowed</param>
    /// <param name="canCastleQueenside">If true then caslting queenside is allowed</param>
    /// <param name="bit">Holds the bitboard with one bit set showing where king is located</param>
    /// <param name="attacker">Bitboard of side to move</param>
    /// <param name="defender">Bitboard of side not to move</param>
    /// <returns>A Bitboard that represents all the valid king moves.</returns>
    static public Bitboard KingMoves(bool bColor, bool canCastleKingside, bool canCastleQueenside,
      Bitboard bit, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket=0;
      //Bitboard pBit=bit;
      int row=BitRow(bit);
      int colm=BitColm(bit);

      if( colm != 1 )
        moveBucket |= bit << 1;
      if( colm != 8 )
        moveBucket |= bit >> 1;

      if( row != 8 )
      {
        moveBucket |= bit << 8;
        if( colm != 1  )
          moveBucket |= bit << 9;
        if( colm != 8 )
          moveBucket |= bit << 7;
      }

      if( row != 1 )
      {
        moveBucket |= bit >> 8;
        if( colm != 1 )
          moveBucket |= bit >> 7;
        if( colm != 8 )
          moveBucket |= bit >> 9;
      }

      //Check for castling privileges
      if (canCastleKingside)
      {
        if( bColor )
        {
          // White king must sit on proper square.
          if ((bit & 0x08) == 0x08)
          {
            // Check white kingside castling
            if (((attacker | defender) & 0x07) == 0x01)
              moveBucket |= bit >> 2;
          }
        }
        else
        {
          // Check white kingside castling
          // Black king must sit on proper square.
          if ((bit & 0x0800000000000000) == 0x0800000000000000)
          {
            if (((attacker | defender) & 0x0700000000000000) == 0x0100000000000000)
              moveBucket |= bit >> 2;
          }
        }
      }
      if (canCastleQueenside)
      {
        if( bColor )
        {
          // White king must sit on proper square.
          if ((bit & 0x08 )== 0x08)
          {
            // Check white kingside castling
            if (((attacker | defender) & 0xF0) == 0x80)
              moveBucket |= bit << 2;
          }
        }
        else
        {
          // Check white kingside castling
          // Black king must sit on proper square.
          if ((bit & 0x0800000000000000) == 0x0800000000000000)
          {

            if (((attacker | defender) & 0xF000000000000000) == BitboardSquare.MaskHighBit)
              moveBucket |= bit << 2;
          }
        }
      }

      return moveBucket;
    }

    /// <summary>
    /// This routine is used to calculate all of the squares between an attacking
    /// piece and the attacked piecs.  It requires that only one bit be set in each
    /// of the bitboards.  Only calculates sliding piece moves such as rooks and
    /// bishops.
    /// </summary>
    /// <param name="attacker">bit set of attacking piece</param>
    /// <param name="attacked">bit set of defending piece</param>
    /// <returns></returns>
    static public Bitboard DirectAttack(Bitboard attacker, Bitboard attacked)
    {
      int arow=BitRow(attacker),acolm=BitColm(attacker);
      int drow=BitRow(attacked),dcolm=BitColm(attacked);
      Bitboard mask = attacker | attacked;
      if( arow == 0 || acolm == 0 || drow == 0 || dcolm == 0 )
        throw new NullReferenceException("getDirectAttack parameter invalid");
      if( arow == drow )
      {
        if( acolm > dcolm )
        {
          while( attacker != attacked )
          {
            attacker <<= 1;
            mask |= attacker;            
          }
        }
        else
        {
          while( attacker != attacked )
          {
            attacker >>= 1;
            mask |= attacker;
          }
        }

      }
      else if( acolm == dcolm )
      {
        if( arow > drow )
        {
          while( attacker != attacked )
          {
            attacker = attacker >> 8;
            mask |= attacker;
          }

        }
        else
        {
          while( attacker != attacked )
          {
            attacker = attacker << 8;
            mask |= attacker;
          }
        }
      }
      else if( arow < drow )
      {
        if( acolm > dcolm )
        {
          while( attacker != attacked )
          {
            attacker = attacker << 9;
            mask |= attacker;
          }
        }
        else
        {
          while( attacker != attacked )
          {
            attacker = attacker << 7;
            mask |= attacker;
          }
        }
      }
      else if( arow > drow )
      {
        if( acolm > dcolm )
        {
          while( attacker != attacked )
          {
            attacker = attacker >> 7;
            mask |= attacker;
          }
        }
        else
        {
          while( attacker != attacked )
          {
            attacker = attacker >> 9;
            mask |= attacker;
          }
        }
      }
      return mask;
    }

    /// <summary>
    /// Returns all bits set for valid moves of specified bishop, including
    /// square in which the bishop protects one of it's own pieces.
    /// Note if you wish to simply get all squares a piece can move
    /// to then simply pass zero for attacker and defender.  If you
    /// do not want to include protected pieces then xor piece board
    /// then AND with function returned value.
    /// </summary>
    /// <param name="bit">One bit set for location of biship</param>
    /// <param name="attacker">The piece board associated with bishop move</param>
    /// <param name="defender">The piece board associated with the opposite color</param>
    /// <returns></returns>
    static public Bitboard BishopMoves(Bitboard bit, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket = 0;
      Bitboard pBit=bit;
      int row = BitRow(bit);
      int colm = BitColm(bit);

      if ((row==0) || (colm == 0)) // This can happen if a king is off the board
        return moveBucket;

      for(int r=row, c=colm;r!=8 && c != 1;r++,c--)
      {
        bit = bit << 9;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }

      bit=pBit;
      for(int r=row, c=colm;r!=8 && c!=8;r++,c++)
      {
        bit = bit << 7;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }

      bit=pBit;
      for(int r=row, c=colm;r!=1 && c != 8;r--,c++)
      {
        bit = bit >> 9;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }

      bit=pBit;
      for(int r=row, c=colm;r!=1 && c!=1;r--,c--)
      {
        bit = bit >> 7;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }
      return moveBucket;
    
    }

    static public Bitboard DiagonalLR(Bitboard bit, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket=0;
      Bitboard pBit=bit;
      int row = BitRow(bit);
      int colm = BitColm(bit);

      if ((row==0) || (colm == 0)) // This can happen if a king is off the board
        return moveBucket;

      for(int r=row, c=colm;r!=8 && c != 1;r++,c--)
      {
        bit = bit << 9;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }

      bit=pBit;
      for(int r=row, c=colm;r!=1 && c != 8;r--,c++)
      {
        bit = bit >> 9;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }
      return moveBucket;
    }
    static public Bitboard DiagonalRL(Bitboard bit, Bitboard attacker, Bitboard defender)
    {
      Bitboard moveBucket=0;
      Bitboard pBit=bit;
      int row = BitRow(bit);
      int colm = BitColm(bit);

      if ((row==0) || (colm == 0)) // This can happen if a king is off the board
        return moveBucket;

      bit=pBit;
      for(int r=row, c=colm;r!=8 && c!=8;r++,c++)
      {
        bit = bit << 7;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }

      bit=pBit;
      for(int r=row, c=colm;r!=1 && c!=1;r--,c--)
      {
        bit = bit >> 7;
        moveBucket |= bit;
        if( (bit & attacker) != 0 || (bit & defender) != 0 )
          break;
      }
      return moveBucket;
    }
    /// <summary>
    /// Determines what horizontal squares a sliding piece may successfully move to, this
    /// would include the capture of an enemy piece.
    /// Note if you wish to simply get all squares a piece can move
    /// to then simply pass zero for attacker and defender.  If you
    /// do not want to include protected pieces then xor piece board
    /// then AND with function returned value.
    /// </summary>
    /// <param name="piece">single bit of piece loation in row or column</param>
    /// <param name="attacker">the bits of all pieces in row or column of the side to move</param>
    /// <param name="defender">the bits of all pieces in row or column of the side not to move</param>
    /// <returns></returns>
    static public Bitboard RankMoves(Bitboard piece, Bitboard attacker, Bitboard defender)
    {
      Bitboard pBit = 0x08;
      Bitboard moveBucket = 0x00;
      int colm = BitColm(piece);
      int workcolm=colm+1;
      pBit = piece;

      //Check all squares to the right
      while (workcolm < 9)
      {
        pBit = (Bitboard)(pBit >> 1);
        moveBucket = (Bitboard)( moveBucket | pBit );
        if( (Bitboard)(pBit & attacker) == 0 )
        {
          if( (Bitboard)(pBit & defender) != 0 )
            break;
        }
        else
          break;
        workcolm++;
      }

      workcolm=colm-1;
      pBit = piece;

      //Check all squares to the left.
      while (workcolm > 0)
      {
        pBit = (Bitboard)(pBit << 1);
        moveBucket = (Bitboard)( moveBucket | pBit );
        if( (Bitboard)(pBit & attacker) == 0 )
        {
          if( (Bitboard)(pBit & defender) != 0 )
            break;
        }
        else
          break;
        workcolm--;
      }
      return moveBucket;
    }

    /// <summary>
    /// Determines what vertical squares a sliding piece may successfully move to, this
    /// would include the capture of an enemy piece.
    /// Note if you wish to simply get all squares a piece can move
    /// to then simply pass zero for attacker and defender.  If you
    /// do not want to include protected pieces then xor piece board
    /// then AND with function returned value.
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="attacker"></param>
    /// <param name="defender"></param>
    /// <returns></returns>
    static public Bitboard FileMoves(Bitboard piece, Bitboard attacker, Bitboard defender)
    {
      Bitboard pBit    = 0x08;
      Bitboard moveBucket = 0x00;
      int row = BitRow(piece);
      int workrow=row;
      pBit = piece;
      if( workrow == 8 )
        workrow++;

      while( workrow < 9 )
      {
        pBit = (Bitboard)(pBit << 8);
        moveBucket = (Bitboard)( moveBucket | pBit );
        if( (Bitboard)(pBit & attacker) == 0 )
        {
          if( (Bitboard)(pBit & defender) != 0 )
            break;
        }
        else
          break;
        workrow++;
      }

      workrow=row;
      if( workrow == 1 )
        workrow--;
      pBit = piece;

      while( workrow > 0 )
      {
        pBit = (Bitboard)(pBit >> 8);
        moveBucket = (Bitboard)( moveBucket | pBit );
        if( (Bitboard)(pBit & attacker) == 0 )
        {
          if( (Bitboard)(pBit & defender) != 0 )
            break;
        }
        else
          break;
        workrow--;
      }
      return moveBucket;
    }

    public enum Suppress{ GETALL = 0x00, KINGS= 0x01, QUEENS = 0x02, ROOKS = 0x04,BISHOPS=0x08, KNIGHTS= 0x10, PAWNS=0x20, PAWNATTACKS=0x40, PAWNILLEGALATTACKS=0x80,PAWNMOVES=0x100, ALL=0xFF };

    /// <summary>
    /// Used to retrieve the square and piece attacks of the attacking army.
    /// You can supress a piece types moves from being generated by passing a
    /// set of enum values in suppresswho.
    /// </summary>
    /// <param name="Attacker"></param>
    /// <param name="Attacked"></param>
    /// <param name="suppress">OR'd values that specify which pieces to ignore.</param>
    /// <param name="pawnMoves">An optional parameter that will be set to legal pawn moves for the position</param>
    /// <returns></returns>
    static public Bitboard Attacks(ChessPosition Attacker,ChessPosition Attacked, Suppress suppress, out Bitboard pawnMoves)
    {
      Bitboard attacked=0;
      Bitboard mask=BitboardSquare.MaskHighBit;
      pawnMoves = 0;

      while(mask != 0)
      {
        // Only if this piece is not pinned.
        if( (Attacker.Pinned & mask) == 0 )
        {
          if((mask & Attacker.Queens) > 0)
          {
            if( (suppress & Suppress.QUEENS) == 0 )
              attacked |= StandardMoves.QueenMoves(mask,Attacker.Board,Attacked.Board);
          }
          else if((mask & Attacker.Rooks) > 0)
          {
            if( (suppress & Suppress.ROOKS) == 0 )
              attacked |= StandardMoves.RookMoves(mask,Attacker.Board,Attacked.Board);
          }
          else if((mask & Attacker.Bishops) > 0)
          {
            if( (suppress & Suppress.BISHOPS) == 0 )
              attacked |= StandardMoves.BishopMoves(mask,Attacker.Board,Attacked.Board);
          }
          else if((mask & Attacker.Knights) > 0)
          {
            if( (suppress & Suppress.KNIGHTS) == 0 )
              attacked |= StandardMoves.KnightMoves(mask,Attacker.Board,Attacked.Board);
          }
          else if((mask & Attacker.Pawns) > 0)
          {
            if( (suppress & Suppress.PAWNS) == 0 )
            {
              if( (suppress & Suppress.PAWNATTACKS) == 0 )
              {
                if( (suppress & Suppress.PAWNILLEGALATTACKS) == 0 )
                  attacked |= StandardMoves.PawnAttacks(mask,Attacker.Color/*,Attacker.Board,Attacked.Board*/);
                else
                  attacked |= (Attacked.Board & StandardMoves.PawnAttacks(mask,Attacker.Color/*,Attacker.Board,Attacked.Board*/));
                // Get enpasant move
                attacked |= StandardMoves.PawnEnpassant(mask, Attacker, Attacked);
              }
              if( (suppress & Suppress.PAWNMOVES) == 0 )
              {
                pawnMoves |= StandardMoves.PawnMoves(mask,Attacker.Color,Attacker.Board,Attacked.Board);
              }
            }
          }
          else if((mask & Attacker.King) > 0)
          {
            if( (suppress & Suppress.KINGS) == 0 )
              attacked |= StandardMoves.KingMoves(Attacker.Color,false,false, mask,Attacker.Board,Attacked.Board);
          }
        }
        mask = mask >> 1;
      }
      //attacked = attacked & ~(Attacker.Board);
      return attacked;
    }

    /// <summary>
    /// Performs the work of building our printable string representations of
    /// our bitboard.
    /// </summary>
    /// <param name="board"></param>
    /// <returns></returns>
    static public string ToString(Bitboard board)
    {
      int ndx=0;
      StringBuilder build = new StringBuilder(100);
      Bitboard mask=BitboardSquare.MaskHighBit; // >> (64 - coBitsToPrint);
      while(mask > 0)
      {
        Bitboard nboard = (mask&board);
        if( nboard > 0)
          build.Append('1');
        else
          build.Append('0');
        mask = mask >> 1;
        ndx++;
        if( ndx%8 == 0)
        {
          build.Append("\r\n");
        }
      }
      return build.ToString();
    }
    #endregion chessmoves
  }
}
